package com.service1.config

import com.baomidou.mybatisplus.core.MybatisConfiguration
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean
import com.main.config.db.DBBaseConfig
import com.mysql.cj.jdbc.MysqlXADataSource
import io.seata.rm.datasource.DataSourceProxy
import org.apache.ibatis.session.SqlSessionFactory
import org.mybatis.spring.SqlSessionTemplate
import org.mybatis.spring.annotation.MapperScan
import org.mybatis.spring.transaction.SpringManagedTransactionFactory
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.stereotype.Component
import javax.sql.DataSource

@Component
class DBConfig_db1 {
    companion object {
        const val dbName = "db1"
        const val dbNameNoUnderLine = "db1"
        const val basePackages_this_mybatis = "com.service1.db.mybatis.db1.mapper"
        const val basePackages_this_mybatisplus = "com.service1.db.mybatis.db2.mapper"
        const val dataSource_this = "dataSource_$dbName"
        const val sqlSessionFactory_this = "sqlSessionFactory_$dbName"
        const val sqlSessionTemplate_this = "sqlSessionTemplate_$dbName"
        const val configurationProperties_this = "spring.datasource.$dbNameNoUnderLine"
    }

    @Component
    @ConfigurationProperties(prefix = configurationProperties_this)
    class ConfigModel : DBBaseConfig.DBConfigModel()

    @Configuration
    @MapperScan(
        basePackages = [basePackages_this_mybatis, basePackages_this_mybatisplus],
        sqlSessionFactoryRef = sqlSessionFactory_this
    )
    class Config {
        @Bean(name = [dataSource_this])
        fun db1DataSource(config: ConfigModel): DataSource {
            val mysqlXaDataSource = MysqlXADataSource()
            mysqlXaDataSource.setUrl(config.url)
            mysqlXaDataSource.pinGlobalTxToPhysicalConnection = true
            mysqlXaDataSource.password = config.password
            mysqlXaDataSource.user = config.username
            mysqlXaDataSource.pinGlobalTxToPhysicalConnection = true
            val xaDataSource = AtomikosDataSourceBean()
            xaDataSource.xaDataSource = mysqlXaDataSource
            xaDataSource.uniqueResourceName = dataSource_this
            xaDataSource.minPoolSize = config.minPoolSize
            xaDataSource.maxPoolSize = config.maxPoolSize
            xaDataSource.maxLifetime = config.maxLifetime
            xaDataSource.borrowConnectionTimeout = config.borrowConnectionTimeout
            xaDataSource.loginTimeout = config.loginTimeout
            xaDataSource.maintenanceInterval = config.maintenanceInterval
            xaDataSource.maxIdleTime = config.maxIdleTime
            xaDataSource.testQuery = config.testQuery
            return xaDataSource
        }

        @Bean(name = [sqlSessionFactory_this])
        @Throws(Exception::class)
        fun sqlSessionFactory(@Qualifier(dataSource_this) dataSource: DataSource): SqlSessionFactory {
            val bean = MybatisSqlSessionFactoryBean()
            bean.setDataSource(DataSourceProxy(dataSource))
            bean.setTransactionFactory(SpringManagedTransactionFactory())
            val configuration = MybatisConfiguration()
            configuration.isCallSettersOnNulls = true
            bean.configuration = configuration
            return bean.getObject()!!
        }

        @Bean(name = [sqlSessionTemplate_this])
        fun sqlSessionTemplate(@Qualifier(sqlSessionFactory_this) sqlSessionFactory: SqlSessionFactory): SqlSessionTemplate {
            val tmp = SqlSessionTemplate(sqlSessionFactory)
            tmp.configuration.isMapUnderscoreToCamelCase = true
            return tmp
        }
    }
}
